Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

Generic Entity Framework 4.0 Base Repository

Îåêßíçóå áðü ôï ìÝëïò George J. Capnias. Τελευταία δημοσίευση από το μέλος Παναγιώτης Καναβός στις 15-07-2010, 11:02. Υπάρχουν 2 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  15-07-2010, 00:22 59435

    Generic Entity Framework 4.0 Base Repository

    Διάβαζα χτες μία δημοσίευση στο blog του Fredrik Normén για την τελευταία δημιουργία του, το ForkCan.com. Ωραία ιδέα, παρεπιπτόντως. Κοιτώντας μέσα στον κώδικα που είναι στο site, είδα {1}, {2} implementations για Generic Entity Framework 4.0 Base Repository.

    Αν και μοιάζουν αρκετά, και ξεκινούν από παρόμοιο Interface, μου "ξίνισαν" μιας και το Repository pattern "θα έπρεπε" να είναι συνδυασμένο με το ένα "Unit of Work" pattern. Οπότε ξεκίνησα να γράφω στο Notepad...

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    namespace RepositoryWebAppv2.Model
    {
        public interface IRepository<TEntity, TContext>
            where TEntity : class
            where TContext : class
        {
            IQueryable<TEntity> GetQuery();
            IList<TEntity> FetchAll();
            IList<TEntity> Fetch(Expression<Func<TEntity, bool>> where);
            TEntity FetchSingle(Expression<Func<TEntity, bool>> where);
            int Create(TEntity entity);
            void Update(TEntity entity);
            void Delete(TEntity entity);
        }
    }

    Μετά είπα να "πρωτοτυπήσω" και να κάνω ένα abstract class:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
     
    namespace RepositoryWebAppv2.Model
    {
        [DataObject]
        public abstract class Repository<TEntity, TContext> : IRepository<TEntity, TEntity>
            where TEntity : EntityObject, new()
            where TContext : ObjectContext, new()
        {
            private TContext _ObjectContext;
    
            public Repository()
            {
                _ObjectContext = new TContext();
            }
    
            public Repository(TContext objectContext)
            {
                if (objectContext == null)
                    throw new ArgumentNullException("objectContext");
    
                _ObjectContext = objectContext;
            }
    
            #region ' IRepository<TEntity,TEntity> Members '
    
            public IQueryable<TEntity> GetQuery()
            {
                return _ObjectContext.CreateObjectSet<TEntity>();
            }
    
            [DataObjectMethod(DataObjectMethodType.Select, true)]
            public IList<TEntity> FetchAll()
            {
                return _ObjectContext.CreateObjectSet<TEntity>().ToList();
            }
    
            public IList<TEntity> Fetch(Expression<Func<TEntity, bool>> where)
            {
                return _ObjectContext.CreateObjectSet<TEntity>().Where(where).ToList();
            }
    
            public TEntity FetchSingle(Expression<Func<TEntity, bool>> where)
            {
                return _ObjectContext.CreateObjectSet<TEntity>().SingleOrDefault(where);
            }
    
            [DataObjectMethod(DataObjectMethodType.Insert, true)]
            public int Create(TEntity entity)
            {
                return _ObjectContext.CreateObjectSet<TEntity>().AddObject(entity);
            }
    
            [DataObjectMethod(DataObjectMethodType.Update, true)]
            public void Update(TEntity entity)
            {
                if (entity.EntityState == EntityState.Detached)
                    _ObjectContext.Attach(entity);
            }
    
            [DataObjectMethod(DataObjectMethodType.Delete, true)]
            public void Delete(TEntity entity)
            {
                _ObjectContext.CreateObjectSet<TEntity>().DeleteObject(entity);
            }
    
            #endregion
        }
    
    }
    }

    "Καμαρώνοντας" τη δημιουργία μου, είπα να τη τρέξω, αλλά η μόνη "πρόχειρη" έκδοση Visual Studio που είχα ήταν το Visual Studio 2008, μιας και βαριώμουν να σηκώσω ένα άλλο VM που είχε Visual Studio 2010. Κάνοντας copy & paste τον κώδικά μου, έφτιαξα και το πρώτο repository entity μου:

    1
    2
    3
    4
    5
     
    namespace RepositoryWebAppv2.Model
    {
        public class CustomerRepository : Repository<Customer, NorthwindEntities>
        { }
    }

    Και αυτό που πήρα ήταν ένα σφάλμα - δεν χρειάστηκε πολύ να συνειδιτοποιήσω ότι ο κώδικας που είχα γράψει είχε target το EF4 και όχι το EF που έχει το .NET Framework v3.5 SP1. "Μικρό το κακό" σκέφτηκα, και έγραψα μερικές Extension Methods για να το "στρώσω" και για το EF1:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
        public static partial class Extensions
        {
            public static ObjectQuery<T> CreateObjectSet<T>(this ObjectContext objectcontext)
                where T : EntityObject
            {
                return objectcontext.GetType().GetProperties().OfType<ObjectQuery<T>>().FirstOrDefault();
            }
    
            public static void DeleteObject<T>(this ObjectQuery<T> entityset, T entity)
                where T : EntityObject
            {
                entityset.Context.DeleteObject(entity);
            }
    
            public static int AddObject<T>(this ObjectQuery<T> entityset, T entity)
                where T : EntityObject
            {
                try
                {
                    entityset.Context.AddObject(entityset.Name, entityset);
                }
                catch (Exception)
                {
                    return 0;
                }
    
                return 1;
            }
        }

    Και ενώ ήμουν "χαρούμενος" ότι θα έτρεχε, είδα ότι το extension method CreateObjectSet() δεν μου γύριζε ObjectSet<T> που ήθελα, αλλά επέστρεφε πάντα null.

    Κάποια ιδέα γιατί το εν λόγω method δεν συμπεριφέρεται όπως περίμενα; "Φώτα" κάποιος;

     

    George J.


    George J. Capnias: Χειροπρακτικός Υπολογιστών, Ύψιστος Γκουράρχης της Κουμπουτερολογίας
    w: capnias.org, t: @gcapnias, l: gr.linkedin.com/in/gcapnias
    dotNETZone.gr News
    Δημοσίευση στην κατηγορία: , ,
  •  15-07-2010, 01:15 59438 σε απάντηση της 59435

    Απ: Generic Entity Framework 4.0 Base Repository

    Η GetQuery() στο RepositoryWebAppv2.Model σου επιστρέφει ένα IQueryable γιατί καλείς την CreateObjectSet<TEntity>(). Στο extension, που δημιουργείται το IQueryable ή μήπως μου διαφεύγει κάτι;


    Ακόμα κι ένας άνθρωπος μπορεί ν' αλλάξει τον κόσμο. Μη θέλεις να κυβερνήσεις. Απλά δείξε το μονοπάτι κι ο κόσμος θ' ακολουθήσει!!
  •  15-07-2010, 11:02 59439 σε απάντηση της 59435

    Απ: Generic Entity Framework 4.0 Base Repository

    Elementary my dear Watson. Η GetProperties σου επιστρέφει ένα array από PropertyInfo, όχι από ObjectQuery<T>. Πρέπει να βάλεις ένα Where( prop => prop.PropertyType == typeof(ObjectQuery<T>) και φυσικά να βάλεις και το κατάλληλο Select.

    Οπότε το one-liner γίνεται

    objectContext.GetType().GetProperties().Where(prop => prop.PropertyType == typeof(ObjectQuery<T>)).Select(prop => (ObjectQuery<T>) prop.GetValue(objectContext,null))

    ή σε LINQ syntax

    var queries=from prop in objectContext.GetType().GetProperties()
                     where prop.PropertyType == typeof(ObjectQuery<T>)
                     select (ObjectQuery<T>) prop.GetValue(objectContext,null);
    return queries.FirstOrDefault();
    Και μετά μου λες για γκοφρέτες ...

    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems